﻿using ActionSystem.Core.Utils;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XMLib;
using ActionSystem.Core.EventSystem;
namespace ActionSystem.Core
{
    /// <summary>
    /// 基本状态机
    /// 
    /// 启用USE_DEEP_COPY宏定义可以禁止状态机之间配置共享，
    /// 默认状态机之间配置共享，不应该运行时修改配置
    /// </summary>
    [DefaultExecutionOrder(ActionSystemConstDefine.StateMachineExcutionOrder)]
    public class BaseStateMachine : MonoBehaviour
    {
        #region 内部事件
        EventSystem.EventSystem eventSystem = new EventSystem.EventSystem();
        public void RegisterListener(int eventId, IEvent handler)
        {
            eventSystem.RegisterListener(eventId,handler);
        }
        public void UnRegisterListenser(int eventId, IEvent handler)
        {
            eventSystem.UnRegisterListenser(eventId,handler);
        }
        public void RaiseEvent(int eventId, EventArg arg)
        {
            eventSystem.RaiseEvent(eventId,arg);
        }
        #endregion
        #region 配置数据
        //缓存一些配置，避免重复加载
        static Dictionary<string, MachineConfig> globalConfigCache = new Dictionary<string, MachineConfig>();
        [SerializeField]
        private TextAsset configFile;
        [SerializeField]
        private bool interpolateActor=true;
        private MachineConfig configData;
        bool instanced = false;
        protected bool HasStates => states.Count > 0;
        public void InstanceMachine()
        {
            float s = Time.realtimeSinceStartup;
            //判断是否是已经实例化
            if (instanced)
            {
                return;
            }
            instanced = true;
            if (configFile != null)
            {
                //先从缓存中获取
                if (globalConfigCache.TryGetValue(configFile.name, out MachineConfig machineConfig))
                {
                    configData = machineConfig;
                }
                else
                {
                    configData = DataUtility.FromJson<MachineConfig>(configFile.text);
                    globalConfigCache.Add(configFile.name, configData);
                }
                if (configData == null)
                {
                    throw new System.Exception($"{configFile.name}配置数据有误");
                }
                //实例化state
                foreach (var state in configData.states)
                {
                    BaseState rawState = state.state;
                    StateCache sc = new StateCache(rawState, this);
                    states.Add(state.state.UID, sc);
                }

            }
            //Debug.Log(gameObject.name + $" instance time: {1000 * (Time.realtimeSinceStartup - s)}ms");
        }
        #endregion
        #region Slot
        Dictionary<int, Transform> slots = new Dictionary<int, Transform>();
        public void ResetSlot()
        {
            if (slots == null)
            {
                slots = new Dictionary<int, Transform>();
            }
            slots.Clear();
            Slot[] ss = GetComponentsInChildren<Slot>();
            foreach (var s in ss)
            {
                if (!slots.ContainsKey(s.SlotID))
                {
                    slots.Add(s.SlotID, s.transform);
                }
            }
            if (!slots.ContainsKey(SlotNameAttribute.Root))
            {
                slots.Add(SlotNameAttribute.Root, transform);
            }
            else
            {
                slots[SlotNameAttribute.Root] = transform;
            }
        }
        public Transform GetSlotTransform(int slotID)
        {
            if (slots != null)
            {
                slots.TryGetValue(slotID, out Transform res);
                return res;
            }
            else
            {
                throw new RuntimeException("slots 为null");
            }

        }
        #endregion
        #region Layer
        /// <summary>
        /// 获取boxType对应的Layer
        /// </summary>
        /// <param name="boxType"></param>
        /// <returns></returns>
        public int GetUnityLayer(int boxType)
        {
            return ActionSystemManager.Instance.GetUnityLayer(boxType);
        }
        /// <summary>
        /// 获取boxType可以检测的LayerMask
        /// </summary>
        /// <param name="boxType"></param>
        /// <returns></returns>
        public int GetUnityLayerMask(int boxType)
        {
            return ActionSystemManager.Instance.GetUnityLayerMask(boxType);
        }
        /// <summary>
        /// 获取BoxType
        /// </summary>
        /// <param name="unityLayer">unity内置的Layer</param>
        /// <returns></returns>
        public int GetBoxType(int unityLayer)
        {
            return ActionSystemManager.Instance.GetBoxType(unityLayer);
        }
        public int GetConflictPriority(int attackingType,int attackedType)
        {
            return ActionSystemManager.Instance.GetConflictPriority(attackingType, attackedType);
        }
        #endregion
        #region 时间分割
        int _localCurrentTimeSplit = 1;
        int _localNextTimeSplit = 1;
        int splitCount = 0;
        public int CurrentTimeSplit
        {
            get
            {
                return parentSM == null ? _localCurrentTimeSplit : parentSM.CurrentTimeSplit;
            }
            private set
            {
                if (value <= 0)
                {
                    Debug.Log(this.name + "'s TimeSplit 不能小等于0");
                    value = 1;
                }
                _localCurrentTimeSplit = value;
            }
        }
        /// <summary>
        /// 设置时间分割，如果是子状态机，则无效
        /// </summary>
        public int LocalNextTimeSplit
        {
            get
            {
                return _localNextTimeSplit;
            }
            set
            {
                if (value <= 0)
                {
                    value = 1;
                }
                _localNextTimeSplit = value;
            }
        }
        #endregion
        #region 顿帧
        private int _pauseFrameCount = 0;
        private int newPauseFrameCount = 0;
        public const int INFINITY = int.MaxValue;
        bool setPause = false;
        bool _isPause = false;
        /// <summary>
        /// 这个参数是否已经更新过
        /// </summary>
        bool _pauseUpdate = false;
        bool PauseUpdate { get => _pauseUpdate; set { _pauseUpdate = value; } }
        /// <summary>
        /// 设置停顿的物理帧数，如果是子状态机，则无效
        /// </summary>
        /// <param name="pauseFrameCount"></param>
        public void SetPauseCount(int pauseFrameCount)
        {
            if (parentSM == null)
            {
                newPauseFrameCount = pauseFrameCount;
            }
            else
            {
                newPauseFrameCount = 0;
            }
            setPause = true;
        }
        /// <summary>
        /// 剩余停顿的逻辑帧数
        /// </summary>
        public int PauseFrameCount
        {
            get { return _pauseFrameCount; }
        }
        /// <summary>
        /// 是否处于顿帧期间
        /// </summary>
        public bool IsPaused
        {
            get
            {
                if (parentSM != null)
                {
                    return parentSM.IsPaused;
                }
                return _isPause;
            }
        }
        /// <summary>
        /// 清除顿帧
        /// </summary>
        public void ClearPauseCount()
        {
            SetPauseCount(0);
        }
        #endregion
        #region 子状态机
        List<BaseStateMachine> addChildCache = new List<BaseStateMachine>();
        List<BaseStateMachine> removeChildCache = new List<BaseStateMachine>();
        List<BaseStateMachine> childSMs = new List<BaseStateMachine>();
        public List<BaseStateMachine> ChildSMs => childSMs;
        BaseStateMachine parentSM;
        public BaseStateMachine Parent => parentSM;
        public IEnumerable<BaseStateMachine> GetChildAndGrandChild()
        {
            foreach (var child in childSMs)
            {
                yield return child;
                foreach (var grandChild in child.GetChildAndGrandChild())
                {
                    yield return grandChild;
                }
            }
        }
        /// <summary>
        /// 添加子状态机
        /// </summary>
        /// <param name="child"></param>
        /// <returns>是否成功</returns>
        public bool AddChildSM(BaseStateMachine child)
        {
            if (child.parentSM == null && !childSMs.Contains(child) && !addChildCache.Contains(child))
            {
                addChildCache.Add(child);
                return true;
            }
            return false;
        }
        public bool RemoveChildSM(BaseStateMachine child)
        {
            if (childSMs.Contains(child) && !removeChildCache.Contains(child))
            {
                removeChildCache.Add(child);
                return true;
            }
            return false;
        }

        #endregion
        #region 被动逻辑
        List<BasePassiveAction> passiveActions = new List<BasePassiveAction>();
        public void AddPassiveAction(BasePassiveActionConfig config)
        {
            //var action = new BasePassiveAction(config);
            var action = GeneticPool<BasePassiveAction>.Create();
            action.SetUp(config);
            passiveActions.Add(action);
        }
        #endregion
        #region action更新条件
        //检测是否需要更新到下一个Action
        bool _frameIndexUpdate = true;
        bool FrameIndexUpdate
        {
            get => _frameIndexUpdate;
            set { _frameIndexUpdate = value; }
        }
        #endregion
        #region 状态管理
        #region 状态时间
        StateData _currentStateData;
        public StateData CurrentStateData => _currentStateData;
        StateData _nextStateData;
        public StateData NextStateData => _nextStateData;
        float _logicDeltaTime;
        public float LogicDeltaTime => _logicDeltaTime;
        #endregion
        Dictionary<int, StateCache> states = new Dictionary<int, StateCache>();
        void PustBackState(BaseState state)
        {
            if(state==null)
            {
                return;
            }
            if (HasStates)
            {
                //结束当前状态
                state.Exit();
                //回收
                if (states.TryGetValue(state.UID, out StateCache stateCache))
                {
                    stateCache.PutState(state);
                }
            }
        }
        BaseState _currentState;
        public BaseState CurrentState => _currentState;
        BaseState _nextState;
        public BaseState NextState => _nextState;
        CandidateData candidateData;
        //候选状态
        BaseState _candidateState;
        protected BaseState CandidateState => _candidateState;
        /// <summary>
        /// 状态混合相关
        /// </summary>
        StateBlendData _blendData;
        protected StateBlendData BlendData => _blendData;
        /// <summary>
        /// 设置下一个状态
        /// </summary>
        /// <param name="id">状态id</param>
        /// <param name="transFrame">状态切换混合帧数</param>
        /// <param name="prority">优先级</param>
        /// <returns></returns>
        public bool SetCandidateState(int id, int transFrame = 0, int priority = 0)
        {
            if (!HasStates)
            {
                return false;
            }
            //设置候选状态
            if (transFrame < 0)
            {
                transFrame = 0;
            }
            if (CandidateState == null)
            {
                if (states.TryGetValue(id, out StateCache value))
                {
                    _candidateState = value.GetState();
                    candidateData.id = id;
                    candidateData.priority = priority;
                    candidateData.transFrame = transFrame;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                //优先级大于当前候选状态
                if (priority > candidateData.priority)
                {
                    if (states.TryGetValue(id, out StateCache value))
                    {
                        _candidateState = value.GetState();
                        candidateData.id = id;
                        candidateData.priority = priority;
                        candidateData.transFrame = transFrame;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            return true;
        }
        #endregion
        #region 生命周期   
        /// <summary>
        /// 递归更新暂停参数
        /// </summary>
        void UpdatePause()
        {
            if (PauseUpdate)
            {
                return;
            }
            PauseUpdate = true;
            if (parentSM != null)
            {
                //更新父级的
                parentSM.UpdatePause();
                //重置自己的
                _isPause = false;
                setPause = false;
            }
            else
            {
                if (setPause)
                {
                    _pauseFrameCount = newPauseFrameCount;
                    setPause = false;
                }
                if (_pauseFrameCount > 0)
                {
                    _isPause = true;
                    if (_pauseFrameCount != INFINITY)
                        _pauseFrameCount -= 1;
                }
                else
                {
                    _isPause = false;
                }
            }
        }
        /// <summary>
        /// 更新帧数
        /// </summary>
        public void UpdateFrameIndex()
        {
            #region 更新顿帧
            UpdatePause();
            #endregion
            //可以更新参数
            if (!IsPaused)
            {
                splitCount += 1;
            }
            FrameIndexUpdate = (CurrentTimeSplit == splitCount);
            if (FrameIndexUpdate)
            {
                splitCount = 0;
            }
        }
        /// <summary>
        /// 更新父子关系
        /// </summary>
        public virtual void UpdateRelationship()
        {
            if (FrameIndexUpdate)
            {
                #region 删除子状态机
                if (removeChildCache.Count > 0)
                {
                    foreach (var child in removeChildCache)
                    {
                        if (childSMs.Contains(child))
                        {
                            childSMs.Remove(child);
                            child.parentSM = null;
                        }
                    }
                    removeChildCache.Clear();
                }
                #endregion
                #region 添加子状态机
                if (addChildCache.Count > 0)
                {
                    foreach (var child in addChildCache)
                    {
                        if (child != null && child.parentSM == null &&
                            child.FrameIndexUpdate &&
                            !childSMs.Contains(child))
                        {

                            childSMs.Add(child);
                            child.parentSM = this;
                        }
                    }
                    addChildCache.Clear();
                }
                #endregion
            }

        }
        /// <summary>
        /// 更新内部数据
        /// </summary>
        public virtual void UpdateInnerData()
        {
            if (FrameIndexUpdate)
            {
                if (!IsPaused)
                {
                    #region 切换状态
                    if (HasStates)
                    {
                        if (CurrentState == null)
                        {
                            _currentState = states[configData.firstStateID].GetState();
                            _currentState.Enter();
                            _blendData.isBlending = false;
                            _blendData.priority = 0;
                            _blendData.transTotalFrame = 0;
                            _blendData.transCount = 0;
                            OnStateChangeCallback(CurrentState);
                            foreach (var call in stateMachineChangeCallback)
                            {
                                call.OnStateChange(null, CurrentState, BlendData);
                            }
                        }
                        //有候选状态
                        if (CandidateState != null)
                        {
                            if (NextState != null)
                            {
                                //结束当前状态
                                CurrentState.Exit();
                                PustBackState(CurrentState);
                                //强制下一个状态位当前状态
                                _currentState = NextState;
                                _nextState = null;
                                _currentStateData = _nextStateData;                                
                            }
                            //候选状态设置为下一个状态
                            _nextState = CandidateState;
                            _blendData.priority = candidateData.priority;
                            _blendData.transTotalFrame = candidateData.transFrame;
                            _blendData.transCount = 0;
                            _blendData.isBlending = true;

                            _candidateState = null;
                            candidateData = new CandidateData();
                            //下一个状态的数据
                            _nextStateData.logicTime = 0;
                            _nextStateData.logicDeltaTime = 0;
                            _nextStateData.weight = 0;

                            //传递action
                            NextState.InheritingActions(CurrentState);
                        }
                        //混合相关
                        if (NextState != null)
                        {
                            bool currentExit = _blendData.isBlending && _blendData.transTotalFrame == _blendData.transCount;
                            //进行一些状态切换相关的操作，转态转入转出，特别是action传递
                            //to do
                            if (currentExit)
                            {
                                CurrentState.Exit();
                            }
                            if (NextState != null && !NextState.Entered)
                            {
                                NextState.Enter();
                                OnStateChangeCallback(NextState);
                                foreach (var call in stateMachineChangeCallback)
                                {
                                    call.OnStateChange(CurrentState, NextState, BlendData);
                                }
                            }
                            //结束
                            if (currentExit)
                            {
                                //交换
                                PustBackState(CurrentState);
                                _currentState = NextState;
                                _nextState = null;
                                _currentStateData = _nextStateData;
                                //当前状态权重设置为1
                                _currentStateData.weight = 1;
                                //结束混合
                                _blendData.isBlending = false;
                            }
                        }
                        #endregion
                        #region 混合相关
                        if (_blendData.isBlending && !IsPaused)
                        {
                            _blendData.transCount += 1;
                        }
                        #endregion
                    }

                    #region 更新TimeSplit
                    //父类不为空则设置为1
                    if (parentSM != null)
                    {
                        LocalNextTimeSplit = 1;
                    }
                    if (_localCurrentTimeSplit != LocalNextTimeSplit)
                    {
                        CurrentTimeSplit = LocalNextTimeSplit;
                    }
                    #endregion
                }                                
            }
            PauseUpdate = false;

            if (interpolateActor)
            {
                startingPosition = transform.position = targetPosition;
                startingRotation = transform.rotation = targetRotation;
            }


        }
        /// <summary>
        /// 更新内部时间
        /// </summary>
        /// <param name="fixedDeltaTime"></param>       
        public virtual void UpdateTime(float fixedDeltaTime)
        {
            //顿帧逻辑时间为0
            if (IsPaused)
            {
                _logicDeltaTime = 0;
            }
            else
            {
                _logicDeltaTime = fixedDeltaTime / CurrentTimeSplit;
            }
            if (HasStates)
            {
                _currentStateData.logicDeltaTime = _logicDeltaTime;
                _currentStateData.logicTime += _logicDeltaTime;
                //混合相关
                if (_blendData.isBlending)
                {
                    _nextStateData.logicDeltaTime = _logicDeltaTime;
                    _nextStateData.logicTime += _logicDeltaTime;
                    //设置权重
                    _nextStateData.weight = _nextStateData.logicTime / (_blendData.transTotalFrame * fixedDeltaTime);
                    _currentStateData.weight = 1 - _nextStateData.weight;
                }else
                {
                    _currentStateData.weight = 1;
                }
            }
        }
        /// <summary>
        /// 更新状态
        /// </summary>
        public void UpdateState()
        {
            if (HasStates)
            {
                //更新当前状态和下一个状态,权重
                CurrentState?.UpdateWeight(CurrentStateData.weight);
                NextState?.UpdateWeight(NextStateData.weight);
                if (FrameIndexUpdate && !IsPaused)
                {
                    //更新当前状态和下一个状态,权重
                    CurrentState.UpdateFrameIndexAndLoop();
                    NextState?.UpdateFrameIndexAndLoop();
                }
            }
        }
        /// <summary>
        /// 被动逻辑
        /// </summary>
        public void PassiveLogicActionUpdate()
        {

            //执行
            foreach (var pa in passiveActions)
            {
                //初始化
                if (!pa.Inited)
                {
                    pa.Init(this);
                }
                //更新
                pa.Update(this, FrameIndexUpdate && !IsPaused, LogicDeltaTime);
                //退出
                if (pa.CheckEnd(this))
                {
                    pa.Remove(this);
                    //放回池子
                    pa.PoolItemDelete();
                }
            }
            //移除已经结束的
            for (int i = passiveActions.Count - 1; i >= 0; i--)
            {
                //清除已经结束的
                if (passiveActions[i].Ended)
                {
                    passiveActions.RemoveAt(i);
                }
            }

        }
        public void HandleEvent()
        {
            eventSystem.Invoke();
        }
        public virtual void ResetInnerData()
        {
            PauseUpdate = false;
            FrameIndexUpdate = false;
            if(interpolateActor)
            {
                targetPosition = transform.position;
                targetRotation = transform.rotation;
            }
        }

        /// <summary>
        /// 将所有数据重置
        /// </summary>
        public virtual void ResetMachine()
        {
            //还原所有数据到初始状态  
            destroyed = false;
            _localCurrentTimeSplit = 1;
            _localNextTimeSplit = 1;
            splitCount = 0;
            _pauseFrameCount = 0;
            newPauseFrameCount = 0;
            childSMs.Clear();
            parentSM = null;
            _frameIndexUpdate = true;
            _pauseUpdate = false;
            eventSystem.ResetSystem();
            if (interpolateActor)
            {
                startingPosition = targetPosition = transform.position;
                startingRotation = targetRotation = transform.rotation;
            }            
            if (HasStates)
            {
                _currentStateData = new StateData();
                _nextStateData = new StateData();
                _currentState = null;
                _nextState = null;
                candidateData = new CandidateData();
                _candidateState = null;
                _blendData = new StateBlendData();
                stateMachineChangeCallback.Clear();
                //重新设置全局action
                for (int i = 0; i < configData.passiveActions.Count; i++)
                {
                    //string pas = DataUtility.ToJson(configData.passiveActions[i]);
                    //AddPassiveAction(DataUtility.FromJson(pas, configData.passiveActions[i].GetType()) as BasePassiveActionConfig);
                    AddPassiveAction(configData.passiveActions[i]);
                }
            }
            ResetSlot();
            Debug.Log(typeof(BaseStateMachine).Name + " inited");
        }
        bool destroyed = false;
        /// <summary>
        /// 销毁
        /// </summary>        
        public virtual void Destroy()
        {
            if (destroyed)
            {
                return;
            }
            destroyed = true;
            //强制移除
            foreach (var pa in passiveActions)
            {
                pa.Remove(this);
            }
            for (int i = passiveActions.Count - 1; i >= 0; i--)
            {
                passiveActions.RemoveAt(i);
            }
            if (HasStates)
            {
                foreach (var call in stateMachineChangeCallback)
                {
                    call.OnDestroy();
                }
                //清理状态
                CurrentState?.Exit();
                PustBackState(CurrentState);
                if (NextState != null)
                {
                    NextState.Exit();
                    PustBackState(NextState);
                }
            }
            addChildCache.Clear();
            removeChildCache.Clear();
            Debug.Log("SM Destroy");
        }
        #endregion
        #region 位置差值
        private Vector3 startingPosition;
        private Vector3 targetPosition;

        private Quaternion startingRotation;
        private Quaternion targetRotation;
        /// <summary>
        /// 位置差值
        /// </summary>
        /// <param name="updateTime">渲染时间</param>
        /// <param name="fixedTime">逻辑更新时间</param>
        public void ProcessInterpolation(float updateTime, float fixedTime)
        {
            if (!interpolateActor)
            {
                return;
            }
            float interpolationFactor = (updateTime - fixedTime) / (ActionSystemManager.Instance.GlobalConfig.FrameTime);
            transform.position = Vector3.Lerp(startingPosition, targetPosition, interpolationFactor);
            transform.rotation = Quaternion.Slerp(startingRotation, targetRotation, interpolationFactor);
        }
        #endregion
        #region callback
        /// <summary>
        /// 切换状态时回调
        /// </summary>
        protected virtual void OnStateChangeCallback(BaseState nextState)
        {

        }
        HashSet<IStateMachineChange> stateMachineChangeCallback = new HashSet<IStateMachineChange>();
        public void AddStateChanegCallback(IStateMachineChange callback)
        {
            if (!stateMachineChangeCallback.Contains(callback))
            {
                stateMachineChangeCallback.Add(callback);
            }
        }
        public void RemoveStateChanegCallback(IStateMachineChange callback)
        {
            if (stateMachineChangeCallback.Contains(callback))
            {
                stateMachineChangeCallback.Remove(callback);
            }
        }
        #endregion
        #region UnityAPI
        public virtual void Awake()
        {
            InstanceMachine();
        }
        private void OnDestroy()
        {
            //Don't set transform.parent=null
            Destroy();
            //从ActionSystemManager中移除
            if (ActionSystemManager.Instance != null)
            {
                ActionSystemManager.Instance.DestroySM(this);
            }

        }
        #endregion
    }
    public struct StateData
    {
        public float logicTime;
        public float logicDeltaTime;
        public float weight;
    }
    public struct StateBlendData
    {
        public bool isBlending;
        public int transTotalFrame;
        public int transCount;
        public int priority;

    }
    struct CandidateData
    {
        public int id;
        public int transFrame;
        public int priority;
    }
    class StateCache
    {
        BaseStateMachine stateMachine;
        Queue<BaseState> caches = new Queue<BaseState>();
        BaseState raw;
        public StateCache(BaseState raw, BaseStateMachine stateMachine)
        {
            this.raw = raw;
            this.stateMachine = stateMachine;
            BaseState copyState = InstanceState(raw);
            PutState(copyState);
        }
        private BaseState InstanceState(BaseState raw)
        {
#if USE_DEEP_COPY
            //使用深度拷贝，配置不共享
            var copyState = DeepCopy.DeepCopier.Copy(raw);
#else
            //使用浅拷贝，共享配置数据，当前一个Action配置修改后，其他角色的Action也会被修改
            var copyState = ShadowCopy.Copy<BaseState>(raw);
#endif
            copyState.OnStateInstance(stateMachine);
            return copyState;
        }

        public BaseState GetState()
        {
            if (caches.Count == 0)
            {
                return InstanceState(raw);

            }
            else
            {
                return caches.Dequeue();
            }
        }
        public void PutState(BaseState state)
        {
            caches.Enqueue(state);
        }
    }
}
